/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * The sample smart contract for documentation topic:
 * Writing Your First Blockchain Application
 */

package main

/* Imports
 * 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation
 * 2 specific Hyperledger Fabric specific libraries for Smart Contracts
 */
import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/common/flogging"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	sc "github.com/hyperledger/fabric/protos/peer"
	"strings"
	"time"
)

// Define the Smart Contract structure
type SmartContract struct {
}

var logger = shim.NewLogger("Tracker")

// Define the car structure, with 4 properties.  Structure tags are used by encoding/json library
type Car struct {
	Make   string `json:"make"`
	Model  string `json:"model"`
	Colour string `json:"colour"`
	Owner  string `json:"owner"`
	Price  string `json:"price"`
}

type Product struct {
	//ProductId   string `json:"productId"`  //prefix PD   index
	Input    string `json:"input"` //entityid
	Output   string `json:"output"`
	Time     string `json:"time"`
	State    string `json:"state"`    //1 or 0
	Level    string `json:"level"`    //++
	Operator string `json:"operator"` //EmployeId
	Others   string `json:"others"`
	Target   string `json:"target"`
}

type Entity struct {
	//EntityId   string `json:"entityid"`  //prefix ETD   index
	Name string `json:"name"`
	//Level  string `json:"level"`
	Address string   `json:"address"`
	Proxies []string `json:"proxies"`
}

type Employee struct {
	//EmployeId   string `json:"employeid"`  //prefix EPD  index
	EntityId string `json:"entityid"`
	Name     string `json:"name"`
	Alias    string `json:"alias"`
	Address  string `json:"address"`
	Monitor  string `json:"monitor"`
}

/*
   Store a product
   args : 1, product id from scan code; 2, employee id ; 3 other infos

*/
func (s *SmartContract) inputProduct(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	var err error
	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}
	employeeAsBytes, err := APIstub.GetState("EPD" + args[1])
	if err != nil {
		return shim.Error("Failed to get Product" + err.Error())
	} else if employeeAsBytes == nil {
		return shim.Error("The Employee doesn't exist")
	}
	var employee Employee
	err = json.Unmarshal(employeeAsBytes, &employee)
	if err != nil {
		return shim.Error(err.Error())
	}
	productAsBytes, err := APIstub.GetState("PD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if productAsBytes != nil {
		return shim.Error("The Entity already exists")
	}

	//local, err := time.LoadLocation("PRC")
	//if err != nil {
	//	return shim.Error(err.Error())
	//}
	//tNow := time.Now().In(local)
	timeNow := "2006-01-02"
	product := Product{employee.EntityId, "", timeNow, "0", "0", "EPD" + args[1], args[2], ""}
	productAsBytes, err = json.Marshal(product)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = APIstub.PutState("PD"+args[0], productAsBytes)
	if err != nil {
		return shim.Error("Create Entity Failed")
	}

	return shim.Success(nil)
}

/*
   Shift a product
   args : 1, product id from scan code; 2, employee name ; 3 target Entity id ;4 other infos
*/
func (s *SmartContract) outputProduct(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}
	productAsBytes, err := APIstub.GetState("PD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Product" + err.Error())
	} else if productAsBytes == nil {
		return shim.Error("The Product doesn't exist")
	}
	var product Product
	err = json.Unmarshal(productAsBytes, &product)
	if err != nil {
		return shim.Error(err.Error())
	}

	employeeAsBytes, err := APIstub.GetState("EPD" + args[1])
	if err != nil {
		return shim.Error("Failed to get Product" + err.Error())
	} else if employeeAsBytes == nil {
		return shim.Error("The Employee doesn't exist")
	}
	var employee Employee
	err = json.Unmarshal(employeeAsBytes, &employee)
	if err != nil {
		return shim.Error(err.Error())
	}

	product.Output = employee.EntityId
	product.State = "1"
	product.Operator = "EPD" + args[1]
	product.Target = "ETD" + args[2]
	level, err := strconv.Atoi(product.Level)
	level += 1
	product.Level = strconv.Itoa(level)
	local, err := time.LoadLocation("PRC")
	if err != nil {
		return shim.Error(err.Error())
	}
	tNow := time.Now().In(local)
	timeNow := tNow.Format("2006-01-02 15:04:05")
	product.Time = timeNow
	productAsBytes, err = json.Marshal(product)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = APIstub.PutState("PD"+args[0], productAsBytes)
	if err != nil {
		return shim.Error("Failed Operate" + err.Error())
	}
	return shim.Success(nil)
}

/*
   track a product
   args : 1, product id from scan code; 2, employee id ;3 is Amdin is 1 or 0
*/
func (s *SmartContract) trackProduct(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}
	//判断货物是否存在
	productAsBytes, err := APIstub.GetState("PD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Product" + err.Error())
	} else if productAsBytes == nil {
		return shim.Error("The Product doesn't exist")
	}
	var product Product
	err = json.Unmarshal(productAsBytes, &product)
	if err != nil {
		return shim.Error(err.Error())
	}
	if strings.EqualFold(product.Output, "") {
		return shim.Error("The Product doesn't output")
	}
	//获取雇员信息
	employeeAsBytes, err := APIstub.GetState("EPD" + args[1])
	if err != nil {
		return shim.Error("Failed to get Employee" + err.Error())
	} else if employeeAsBytes == nil {
		return shim.Error("The Employee doesn't exist")
	}

	var employee Employee

	err = json.Unmarshal(employeeAsBytes, &employee)
	if err != nil {
		return shim.Error(err.Error())
	}
	//获取商品历史记录，将商品出货方ETD组成数组
	resultIterator, err := APIstub.GetHistoryForKey("PD" + args[0])
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultIterator.Close()

	from := ""
	to := ""
	for resultIterator.HasNext() {
		response, err := resultIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		var recent Product
		err = json.Unmarshal(response.Value, &recent)
		if err != nil {
			return shim.Error(err.Error())
		}
		if strings.EqualFold(recent.Output, employee.EntityId) {
			to = recent.Target
		}
		if strings.EqualFold(recent.Target, employee.EntityId) {
			from = recent.Output
		}
	}

	//出货方无上家，则返回他自己和下家（没有就不返回）
	//if level <= 1 {
	//	entityAsBytes, err :=APIstub.GetState(track[level])
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	} else if employeeAsBytes == nil {
	//		return shim.Error("The Product Output is not in any Entity")
	//	}
	//	var entity Entity
	//	err = json.Unmarshal(entityAsBytes, &entity)
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	}
	//	var result []Entity
	//	if level + 1 >= len(track) {
	//		result = []Entity{entity}
	//	} else {
	//		entityAsBytes, err =APIstub.GetState(track[level])
	//		if err != nil {
	//			return shim.Error(err.Error())
	//		} else if employeeAsBytes == nil {
	//			return shim.Error("The Product Output is not in any Entity")
	//		}
	//		var nextEntity Entity
	//		err = json.Unmarshal(entityAsBytes, &nextEntity)
	//		if err != nil {
	//			return shim.Error(err.Error())
	//		}
	//		result = []Entity{entity, nextEntity}
	//	}
	//	resultjson ,err := json.Marshal(result)
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	}
	//	return shim.Success(resultjson)
	//}
	//查出所有出货相关Entity信息
	//var line []Entity
	//for i:=0;i<len(track)-1;i++ {
	//	entityAsBytes, err :=APIstub.GetState(track[i+1])
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	} else if employeeAsBytes == nil {
	//		return shim.Error("The EntityId is not any Entity")
	//	}
	//	var entity Entity
	//	err = json.Unmarshal(entityAsBytes, &entity)
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	}
	//	line = append(line, entity)
	//}
	////是管理员则返回全部信息
	//if strings.EqualFold(employee.Alias, "Admin") {
	//	resultjson, err := json.Marshal(line)
	//	if err != nil {
	//		return shim.Error(err.Error())
	//	}
	//	return shim.Success(resultjson)
	//}
	////不是则只返回上下家和自己
	//var partline []Entity
	//if level >= len(line) {
	//	partline = line[level-2:]
	//} else {
	//	partline = line[level-2 : level]
	//}
	//resultjson, err := json.Marshal(partline)
	//if err != nil {
	//	return shim.Error(err.Error())
	//}
	//return shim.Success(resultjson)

	resultMap := make(map[string]Entity)
	if from != "" {
		entityAsBytes, err := APIstub.GetState(from)
		if err != nil {
			return shim.Error(err.Error())
		} else if entityAsBytes == nil {
			return shim.Error("History is wrong")
		}
		var entity Entity
		err = json.Unmarshal(entityAsBytes, &entity)
		if err != nil {
			return shim.Error(err.Error())
		}
		resultMap["from"] = entity
	}
	if to != "" {
		entityAsBytes, err := APIstub.GetState(to)
		if err != nil {
			return shim.Error(err.Error())
		} else if entityAsBytes == nil {
			return shim.Error("History is wrong")
		}
		var entity Entity
		err = json.Unmarshal(entityAsBytes, &entity)
		if err != nil {
			return shim.Error(err.Error())
		}
		resultMap["to"] = entity
	}
	resultjson, err := json.Marshal(resultMap)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(resultjson)
}

func (s *SmartContract) trackAll(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	//判断货物是否存在
	productAsBytes, err := APIstub.GetState("PD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Product" + err.Error())
	} else if productAsBytes == nil {
		return shim.Error("The Product doesn't exist")
	}
	var product Product
	err = json.Unmarshal(productAsBytes, &product)
	if err != nil {
		return shim.Error(err.Error())
	}
	if strings.EqualFold(product.Output, "") {
		return shim.Error("The Product doesn't output")
	}

	var track []Entity
	//获取商品历史记录，将商品出货方ETD组成数组
	resultIterator, err := APIstub.GetHistoryForKey("PD" + args[0])
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultIterator.Close()

	for resultIterator.HasNext() {
		response, err := resultIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		var recent Product
		err = json.Unmarshal(response.Value, &recent)
		if err != nil {
			return shim.Error(err.Error())
		}
		_, err = strconv.Atoi(recent.Level)
		if err != nil {
			return shim.Error(err.Error())
		}
		if recent.Output != "" {
			entityAsBytes, err := APIstub.GetState(recent.Output)
			if err != nil {
				return shim.Error(err.Error())
			} else if entityAsBytes == nil {
				return shim.Error("History is wrong")
			}
			var entity Entity
			err = json.Unmarshal(entityAsBytes, &entity)
			if err != nil {
				return shim.Error(err.Error())
			}
			track = append(track, entity)
		}
	}
	resultjson, err := json.Marshal(track)
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success(resultjson)
}

/*
   Query proxies  of a entity id;
   args : 1, Entity id; return company ids
*/
func (s *SmartContract) queryProxies(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("query entity error" + err.Error())
	} else if entityAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var entity Entity
	err = json.Unmarshal(entityAsBytes, &entity)
	if err != nil {
		return shim.Error("Error 1:" + err.Error())
	}

	var proxymap = make(map[string]string)

	for _, p := range entity.Proxies {
		itentityAsBytes, err := APIstub.GetState(p)
		var itentity Entity
		err = json.Unmarshal(itentityAsBytes, &itentity)
		if err != nil {
			return shim.Error(err.Error())
		}
		proxymap[string([]rune(p)[3:])] = itentity.Name

	}
	proxiesAsByte, err := json.Marshal(proxymap)
	if err != nil {
		return shim.Error("Error 3:" + err.Error())
	}
	return shim.Success(proxiesAsByte)
}

/*
	args : 1, entity id; 2, proxies
*/
func (s *SmartContract) addProxies(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}
	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("query entity error" + err.Error())
	} else if entityAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var entity Entity
	err = json.Unmarshal(entityAsBytes, &entity)
	if err != nil {
		return shim.Error(err.Error())
	}
	//将以前的代理转化成字符串数组
	var proxies = entity.Proxies
	fmt.Print("err1", proxies)
	//将要添加的代理转化成字符串数组
	var newproxies []string
	err = json.Unmarshal([]byte(args[1]), &newproxies)
	if err != nil {
		return shim.Error("error4")
	}
	fmt.Print("err2", newproxies)
	//合并放回
	//length := len(proxies) + len(newproxies)
	//var finalProxies []string

	finalProxies := proxies[:]
	//for i:= len(proxies);i<length;i++  {
	//	if i < len(proxies) {
	//		finalProxies[i] = proxies[i]
	//	} else {
	//		finalProxies[i] = newproxies[i + len(proxies)]
	//	}
	//}
	for _, p := range newproxies {
		finalProxies = append(finalProxies, "ETD"+p)
	}

	entity.Proxies = finalProxies
	entityAsBytes, err = json.Marshal(entity)
	if err != nil {
		shim.Error(err.Error())
	}
	err = APIstub.PutState("ETD"+args[0], entityAsBytes)
	if err != nil {
		return shim.Error("Fail to add proxies" + err.Error())
	}
	return shim.Success(nil)
}

func (s *SmartContract) queryProduct(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	var err error
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	productAsBytes, err := APIstub.GetState("PD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if productAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var product Product
	err = json.Unmarshal(productAsBytes, &product)
	if err != nil {
		shim.Error(err.Error())
	}
	if product.Input != "" {
		product.Input = string([]rune(product.Input)[3:])
	}
	if product.Output != "" {
		product.Output = string([]rune(product.Output)[3:])
	}
	if product.Operator != "" {
		product.Operator = string([]rune(product.Operator)[3:])
	}
	if product.Target != "" {
		product.Target = string([]rune(product.Target)[3:])
	}

	productAsBytes, err = json.Marshal(product)
	if err != nil {
		shim.Error(err.Error())
	}

	return shim.Success(productAsBytes)
}

func (s *SmartContract) queryEntity(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	var log = flogging.MustGetLogger("step")
	log.Info("step1")
	var err error
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if entityAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var entity Entity
	err = json.Unmarshal(entityAsBytes, &entity)
	if err != nil {
		shim.Error(err.Error())
	}

	proxies := entity.Proxies
	var i = 0
	for _, proxy := range proxies {
		entity.Proxies[i] = string([]rune(proxy)[3:])
		i++
	}

	entityAsBytes, err = json.Marshal(entity)
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(entityAsBytes)
}

/*
   args : 1, employee alias id; return Employee Id,Entity id
*/
func (s *SmartContract) queryEmployee(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	var err error
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}
	employeeAsBytes, err := APIstub.GetState("EPD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Employee:" + err.Error())
	} else if employeeAsBytes == nil {
		return shim.Error("The Employee doesn't exist")
	}

	var employee Employee
	err = json.Unmarshal(employeeAsBytes, &employee)
	if err != nil {
		return shim.Error(err.Error())
	}

	employee.EntityId = string([]rune(employee.EntityId)[3:])
	employeeAsBytes, err = json.Marshal(employee)
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(employeeAsBytes)
}

func (s *SmartContract) updateEntity(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if entityAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var entity Entity
	err = json.Unmarshal(entityAsBytes, &entity)
	if err != nil {
		return shim.Error(err.Error())
	}

	entity.Name = args[1]
	entity.Address = args[2]
	entityAsBytes, err = json.Marshal(entity)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = APIstub.PutState("ETD"+args[0], entityAsBytes)
	if err != nil {
		return shim.Error("Update Entity Failed" + err.Error())
	}
	return shim.Success(nil)
}

func (s *SmartContract) updateEmployee(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 6 {
		return shim.Error("Incorrect number of arguments. Expecting 6")
	}

	employeeAsBytes, err := APIstub.GetState("EPD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Employee:" + err.Error())
	} else if employeeAsBytes == nil {
		return shim.Error("The Employee doesn't exist")
	}

	employee := Employee{"ETD" + args[1], args[2], args[3], args[4], args[5]}
	employeeAsBytes, err = json.Marshal(employee)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = APIstub.PutState("EPD"+args[0], employeeAsBytes)
	if err != nil {
		return shim.Error("Update Employee Failed" + err.Error())
	}

	return shim.Success(nil)
}

func (s *SmartContract) cleanProxies(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if entityAsBytes == nil {
		return shim.Error("The Entity doesn't exist")
	}

	var entity Entity
	err = json.Unmarshal(entityAsBytes, &entity)
	if err != nil {
		return shim.Error(err.Error())
	}

	var proxies []string
	entity.Proxies = proxies
	entityAsBytes, err = json.Marshal(entity)
	if err != nil {
		return shim.Error(err.Error())
	}
	err = APIstub.PutState("ETD"+args[0], entityAsBytes)
	if err != nil {
		return shim.Error("Update Entity Failed" + err.Error())
	}
	return shim.Success(nil)
}

/*
 * The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network
 * Best practice is to have any Ledger initialization in separate function -- see initLedger()
 */
func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
	_, args := APIstub.GetFunctionAndParameters()
	if args[0] != "" {
		var entities [9]Entity
		nums1 := []string{"ETD3000", "ETD3001", "ETD3002", "ETD3003", "ETD4000", "ETD4001", "ETD4002", "ETD4003", "ETD4004"}
		entities[0] = Entity{Name: "北京国将风范贸易发展有限公司", Address: "北京", Proxies: []string{"ETD3001"}}
		entities[1] = Entity{Name: "北京紫酒隆酒业公司", Address: "北京", Proxies: []string{"ETD3002"}}
		entities[2] = Entity{Name: "北京德知源文化有限公司", Address: "北京", Proxies: []string{"ETD3003"}}
		entities[3] = Entity{Name: "天津市九合一商贸有限公司", Address: "天津", Proxies: []string{}}
		entities[4] = Entity{Name: "北京市三合一商贸有限公司", Address: "北京", Proxies: []string{"ETD4001"}}
		entities[5] = Entity{Name: "北京兴顺海酒类销售有限公司", Address: "北京", Proxies: []string{"ETD4002"}}
		entities[6] = Entity{Name: "北京鑫瀚鼎源商贸有限公司", Address: "北京", Proxies: []string{"ETD4003"}}
		entities[7] = Entity{Name: "天津泽诚源酒业销售有限公司", Address: "天津", Proxies: []string{"ETD4004"}}
		entities[8] = Entity{Name: "天津兴隆酒业公司", Address: "天津", Proxies: []string{}}
		var employees [9]Employee
		nums2 := []string{"EPD3100", "EPD3101", "EPD3102", "EPD3103", "EPD4100", "EPD4101", "EPD4102", "EPD4103", "EPD4104"}
		employees[0] = Employee{EntityId: "ETD3000", Name: "白万里", Alias: "User1", Address: "北京", Monitor: "User"}
		employees[1] = Employee{EntityId: "ETD3001", Name: "黄千禧", Alias: "User2", Address: "北京", Monitor: "User"}
		employees[2] = Employee{EntityId: "ETD3002", Name: "洪百胜", Alias: "User3", Address: "北京", Monitor: "User"}
		employees[3] = Employee{EntityId: "ETD3003", Name: "兰十强", Alias: "User4", Address: "北京", Monitor: "User"}
		employees[4] = Employee{EntityId: "ETD4000", Name: "风万福", Alias: "User5", Address: "北京", Monitor: "User"}
		employees[5] = Employee{EntityId: "ETD4001", Name: "林千胜", Alias: "User6", Address: "北京", Monitor: "User"}
		employees[6] = Employee{EntityId: "ETD4002", Name: "火百军", Alias: "User7", Address: "北京", Monitor: "User"}
		employees[7] = Employee{EntityId: "ETD4003", Name: "山十寿", Alias: "User8", Address: "北京", Monitor: "User"}
		employees[8] = Employee{EntityId: "ETD4004", Name: "金一南", Alias: "User9", Address: "北京", Monitor: "User"}
		for i := 0; i < 9; i++ {
			entityAsBytes, err := json.Marshal(&entities[i])
			if err != nil {
				return shim.Error(err.Error())
			}
			err = APIstub.PutState(nums1[i], entityAsBytes)
			if err != nil {
				return shim.Error(err.Error())
			}
			employeeAsBytes, err := json.Marshal(&employees[i])
			if err != nil {
				return shim.Error(err.Error())
			}
			err = APIstub.PutState(nums2[i], employeeAsBytes)
			if err != nil {
				return shim.Error(err.Error())
			}
		}
	}
	return shim.Success(nil)
	return shim.Success(nil)
}

/*
 * The Invoke method is called as a result of an application request to run the Smart Contract "fabcar"
 * The calling application program has also specified the particular smart contract function to be called, with arguments
 */
func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {

	// Retrieve the requested Smart Contract function and arguments
	function, args := APIstub.GetFunctionAndParameters()
	// Route to the appropriate handler function to interact with the ledger appropriately
	logger.Info(function)
	if function == "queryCar" {
		return s.queryCar(APIstub, args)
	} else if function == "initLedger" {
		return s.initLedger(APIstub)
	} else if function == "createCar" {
		return s.createCar(APIstub, args)
	} else if function == "queryAllCars" {
		return s.queryAllCars(APIstub)
	} else if function == "changeCarOwner" {
		return s.changeCarOwner(APIstub, args)
	} else if function == "count" {
		return s.count(APIstub, args)
	} else if function == "track" {
		return s.track(APIstub, args)
	} else if function == "inputProduct" { //the following items for new app
		return s.inputProduct(APIstub, args)
	} else if function == "outputProduct" {
		return s.outputProduct(APIstub, args)
	} else if function == "trackProduct" {
		return s.trackProduct(APIstub, args)
	} else if function == "queryProxies" {
		return s.queryProxies(APIstub, args)
	} else if function == "queryEmployee" {
		return s.queryEmployee(APIstub, args)
	} else if function == "createEntity" {
		return s.createEntity(APIstub, args)
	} else if function == "createEmployee" {
		return s.createEmployee(APIstub, args)
	} else if function == "version" {
		return s.version(APIstub, args)
	} else if function == "queryProduct" {
		return s.queryProduct(APIstub, args)
	} else if function == "addProxies" {
		return s.addProxies(APIstub, args)
	} else if function == "updateEntity" {
		return s.updateEntity(APIstub, args)
	} else if function == "updateEmployee" {
		return s.updateEmployee(APIstub, args)
	} else if function == "queryEntity" {
		return s.queryEntity(APIstub, args)
	} else if function == "trackAll" {
		return s.trackAll(APIstub, args)
	} else if function == "cleanProxies" {
		return s.cleanProxies(APIstub, args)
	} else if function == "queryByCK" {
		return s.queryByCK(APIstub, args)
	} else if function == "createCarS" {
		return s.createCarS(APIstub, args)
	} else if function == "dataCreate" {
		return s.dataCreate(APIstub, args)
	}

	return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract) dataCreate(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	var entities [9]Entity
	nums1 := []string{"ETD3000", "ETD3001", "ETD3002", "ETD3003", "ETD4000", "ETD4001", "ETD4002", "ETD4003", "ETD4004"}
	entities[0] = Entity{Name: "北京国将风范贸易发展有限公司", Address: "北京", Proxies: []string{"ETD3001"}}
	entities[1] = Entity{Name: "北京紫酒隆酒业公司", Address: "北京", Proxies: []string{"ETD3002"}}
	entities[2] = Entity{Name: "北京德知源文化有限公司", Address: "北京", Proxies: []string{"ETD3003"}}
	entities[3] = Entity{Name: "天津市九合一商贸有限公司", Address: "天津", Proxies: []string{}}
	entities[4] = Entity{Name: "北京市三合一商贸有限公司", Address: "北京", Proxies: []string{"ETD4001"}}
	entities[5] = Entity{Name: "北京兴顺海酒类销售有限公司", Address: "北京", Proxies: []string{"ETD4002"}}
	entities[6] = Entity{Name: "北京鑫瀚鼎源商贸有限公司", Address: "北京", Proxies: []string{"ETD4003"}}
	entities[7] = Entity{Name: "天津泽诚源酒业销售有限公司", Address: "天津", Proxies: []string{"ETD4004"}}
	entities[8] = Entity{Name: "天津兴隆酒业公司", Address: "天津", Proxies: []string{}}
	var employees [9]Employee
	nums2 := []string{"EPD3100", "EPD3101", "EPD3102", "EPD3103", "EPD4100", "EPD4101", "EPD4102", "EPD4103", "EPD4104"}
	employees[0] = Employee{EntityId: "ETD3000", Name: "白万里", Alias: "User1", Address: "北京", Monitor: "User"}
	employees[1] = Employee{EntityId: "ETD3001", Name: "黄千禧", Alias: "User2", Address: "北京", Monitor: "User"}
	employees[2] = Employee{EntityId: "ETD3002", Name: "洪百胜", Alias: "User3", Address: "北京", Monitor: "User"}
	employees[3] = Employee{EntityId: "ETD3003", Name: "兰十强", Alias: "User4", Address: "北京", Monitor: "User"}
	employees[4] = Employee{EntityId: "ETD4000", Name: "风万福", Alias: "User5", Address: "北京", Monitor: "User"}
	employees[5] = Employee{EntityId: "ETD4001", Name: "林千胜", Alias: "User6", Address: "北京", Monitor: "User"}
	employees[6] = Employee{EntityId: "ETD4002", Name: "火百军", Alias: "User7", Address: "北京", Monitor: "User"}
	employees[7] = Employee{EntityId: "ETD4003", Name: "山十寿", Alias: "User8", Address: "北京", Monitor: "User"}
	employees[8] = Employee{EntityId: "ETD4004", Name: "金一南", Alias: "User9", Address: "北京", Monitor: "User"}
	for i := 0; i < 9; i++ {
		entityAsBytes, err := json.Marshal(&entities[i])
		if err != nil {
			return shim.Error(err.Error())
		}
		err = APIstub.PutState(nums1[i], entityAsBytes)
		if err != nil {
			return shim.Error(err.Error())
		}
		employeeAsBytes, err := json.Marshal(&employees[i])
		if err != nil {
			return shim.Error(err.Error())
		}
		err = APIstub.PutState(nums2[i], employeeAsBytes)
		if err != nil {
			return shim.Error(err.Error())
		}
	}
	return shim.Success(nil)
}

func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	carAsBytes, _ := APIstub.GetState(args[0])
	return shim.Success(carAsBytes)
}

func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response {
	cars := []Car{
		Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko", Price: "$500"},
		Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad", Price: "$500"},
		Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo", Price: "$500"},
		Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max", Price: "$500"},
		Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana", Price: "$500"},
		Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel", Price: "$500"},
		Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav", Price: "$500"},
		Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari", Price: "$500"},
		Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria", Price: "$500"},
		Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro", Price: "$500"},
	}

	i := 0
	for i < len(cars) {
		fmt.Println("i is ", i)
		carAsBytes, _ := json.Marshal(cars[i])
		APIstub.PutState("ACAR"+strconv.Itoa(i), carAsBytes)
		fmt.Println("Added", cars[i])
		i = i + 1
	}

	return shim.Success(nil)
}

func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 6 {
		return shim.Error("Incorrect number of arguments. Expecting 6")
	}

	var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4], Price: args[5]}
	objectType := "CarOfOwnerAndColor"

	key, _ := APIstub.CreateCompositeKey(objectType, []string{args[4], args[3], args[0]})

	carAsBytes, _ := json.Marshal(car)
	APIstub.PutState(key, carAsBytes)

	return shim.Success(nil)
}

func (s *SmartContract) createCarS(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 6 {
		return shim.Error("Incorrect number of arguments. Expecting 6")
	}

	var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4], Price: args[5]}
	carAsBytes, _ := json.Marshal(car)
	APIstub.PutState(args[0], carAsBytes)

	return shim.Success(nil)
}

func (s *SmartContract) queryByCK(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	responseItertor, err := APIstub.GetStateByPartialCompositeKey("CarOfOwnerAndColor", []string(args[:]))
	if err != nil {
		shim.Error(err.Error())
	}
	var cars []Car
	for responseItertor.HasNext() {
		response, _ := responseItertor.Next()
		var car Car
		err = json.Unmarshal(response.GetValue(), &car)
		cars = append(cars, car)
	}
	carsAsBytes, err := json.Marshal(cars)
	if err != nil {
		shim.Error(err.Error())
	}
	return shim.Success(carsAsBytes)
}

func (s *SmartContract) createEntity(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	logger.Info("entity is being created")

	var err error

	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	entityAsBytes, err := APIstub.GetState("ETD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Entity:" + err.Error())
	} else if entityAsBytes != nil {
		return shim.Error("The Entity already exists")
	}
	var proxies []string
	entity := &Entity{args[1], args[2], proxies}

	entityAsBytes, err = json.Marshal(entity)
	if err != nil {
		return shim.Error(err.Error())
	}

	err = APIstub.PutState("ETD"+args[0], entityAsBytes)
	if err != nil {
		return shim.Error("Create Entity Failed")
	}

	return shim.Success(nil)
}

func (s *SmartContract) createEmployee(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	var err error

	if len(args) != 6 {
		return shim.Error("Incorrect number of arguments. Expecting 6")
	}

	employeeAsBytes, err := APIstub.GetState("EPD" + args[0])
	if err != nil {
		return shim.Error("Failed to get Employee:" + err.Error())
	} else if employeeAsBytes != nil {
		return shim.Error("The Employee already exists")
	}

	employee := &Employee{"ETD" + args[1], args[2], args[3], args[4], args[5]}

	employeeAsBytes, err = json.Marshal(employee)
	if err != nil {
		return shim.Error(err.Error())
	}

	err = APIstub.PutState("EPD"+args[0], employeeAsBytes)
	if err != nil {
		return shim.Error("Create Employee Failed")
	}

	return shim.Success(nil)
}

func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {

	startKey := "CAR0"
	endKey := "CAR999"

	resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// Add a comma before array members, suppress it for the first array member
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"Key\":")
		buffer.WriteString("\"")
		buffer.WriteString(queryResponse.Key)
		buffer.WriteString("\"")

		buffer.WriteString(", \"Record\":")
		// Record is a JSON object, so we write as-is
		buffer.WriteString(string(queryResponse.Value))
		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	fmt.Printf("- queryAllCars:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}

func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	}

	carAsBytes, _ := APIstub.GetState(args[0])
	car := Car{}

	json.Unmarshal(carAsBytes, &car)
	car.Owner = args[1]

	carAsBytes, _ = json.Marshal(car)
	APIstub.PutState(args[0], carAsBytes)

	return shim.Success(nil)
}

func (s *SmartContract) count(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	var resultsIterator shim.StateQueryIteratorInterface
	var err error
	//var resultsIterator  StateQueryIteratorInterface
	//startKey := "CAR0"
	//endKey := "CAR999"
	if len(args) > 2 {
		return shim.Error("Incorrect number of arguments. Expecting 2")
	} else if len(args) == 2 {
		resultsIterator, err = APIstub.GetStateByRange(args[0], args[1])
	} else if len(args) < 2 {
		resultsIterator, err = APIstub.GetStateByRange("", "")
	}

	//resultsIterator, err := APIstub.GetStateByRange(args[0], args[1])
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	count := 0
	buffer.WriteString("[")

	for resultsIterator.HasNext() {
		_, err = resultsIterator.Next()
		count++
	}
	buffer.WriteString("{\"Count\":")
	buffer.WriteString(strconv.Itoa(count))
	buffer.WriteString("]")

	fmt.Printf("- count:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}

func (s *SmartContract) track(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	resultsIterator, err := APIstub.GetHistoryForKey(args[0])

	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// Add a comma before array members, suppress it for the first array member
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"TxId\":")
		buffer.WriteString("\"")
		buffer.WriteString(queryResponse.TxId)
		buffer.WriteString("\"")

		buffer.WriteString(", \"StringValue\":")
		// Record is a JSON object, so we write as-is
		buffer.WriteString(string(queryResponse.Value))
		buffer.WriteString(", \"Timestamp\":")
		buffer.WriteString(queryResponse.Timestamp.String())
		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	fmt.Printf("- track:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())

}

func (s *SmartContract) version(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	return shim.Success([]byte("3.1"))
}

// The main function is only relevant in unit test mode. Only included here for completeness.
func main() {

	// Create a new Smart Contract
	err := shim.Start(new(SmartContract))
	if err != nil {
		fmt.Printf("Error creating new Smart Contract: %s", err)
	}
}
